import numpy as na
import sys
import os 
import cPickle
from xml.sax  import make_parser
from CritObject import CritObject
from CritPoint2 import CritPoint
from CritSegment import CritSegment
import re
import matplotlib.pyplot as pyplot
from viewableImg import *
if( sys.platform == 'darwin' ):
    BIND_TEXT = True
else:
    BIND_TEXT = False
def create(parent):
    return browse(parent)

class browse(object):
    def __init__(self,*args,**kwargs):
        """expecting kwargs to contain some of the following keywords:
            data: a list of arrays to visualize
            mask: a list (possibly empty) of corresponding masks
            grayFactor: a multiplicative scaling for the grayscale
            labelScheme: a dictionary of color,label pairs"""
        try:
            #print kwargs.keys()
            self.vi = viewableImg(**kwargs)
            
            self.DEBUG = False
            if( self.DEBUG ): print "browse__init__"
            pointsFile = kwargs.pop('pointsFile',None)
            self.scale = 1
            self.writedir=os.getcwd()
            self.CriticalObjects = {}
            self.drawpoints = []

            if( pointsFile == None):
                self.pointsFile = "tmp.pckle"
            else:
                self.pointsFile = pointsFile
            if( pointsFile ):
                self.readCriticalObjects()
                
            self.labelScheme = kwargs.get("labelScheme",{"unlabeled":"Red","labeled":"Green"})
            self.currentLabel = kwargs.pop("defaultLabel")
            if( not self.currentLabel in self.labelScheme.keys() ):
                self.currentLabel = self.labelScheme.keys()[0]

             
            self.filename = os.getcwd()
            self.vi.winlevelimage()
        except Exception, error:
            print "failed in browse.__init__() ", error
            sys.exit()

    def writeCriticalObjects(self):
        try:
            fo = open(self.pointsFile,"wb")
            cPickle.dump(self.CriticalObjects,fo)
            fo.close()
        except Exception, error:
            print "failed in writeCriticalObjects", error
    def readCriticalObjects(self):
        try:
            self.writedir = os.path.dirname(self.pointsFile)
            fo = open(self.pointsFile,"rb")
            newObjects = cPickle.load(fo)
            for obj in newObjects:
                objs = self.CriticalObjects.get(obj.className,[])
                objs.append(obj)
                self.CriticalObjects[obj.className] = objs
            
            fo.close()
        except Exception, error:
            pass
    def findNearestCriticalObject(self,p,type="point",verbose=False):
        try:
            minind = 0 
            minobject = self.CriticalObjects[type][0]
            mindist = minobject.getMinimumDistance(p)
            for i in range(1,len(self.CriticalObjects[type])):
                obj = self.CriticalObjects[i]
                dist = obj.getMinimumDistance(p) 
                if( dist < mindist ):
                    mindist = dist
                    minind = i
                    minobject = obj
            if( verbose ):
                print minind, minobject, mindist
            return minind, minpoint, mindist
        except Exception, error:
            print "failed in findNearestCriticalObject", error
            return None

    def deleteNearestCriticalObject(self, p ):
        try:
            minind, minpoint, mindist = self.findNearestCriticalObject(p)
            if( minind != None ):
                del self.CriticalObjects[minind]
            return minpoint
        except Exception, error:
            print "failed in delete nearest_drawpointXY",error
    def modifyNearestCriticalObjectLabel(self,p):
        minind, minpoint, mindist = self.findNearestCriticalObject(p)
        self.CriticalObjects[minind].setLabel(self.currentLabel)
        self.DrawCriticalObjects()

    def DrawAllCriticalObjects(self):
        try:
            self.drawpoints = self.CriticalObjects
        except:
            pass


    def getDisplayScaling(self):
        """return the x-y displaying scaling"""
        return np.matrix(np.identity(self.vi.getMode())*self.scale*self.vi.getScaling())

    def DrawCriticalObjectsXY(self):
        try:
            #print "DrawCriticalObjectsXY",self.CriticalObjects
            self.drawpoints = []
            plims = self.vi.getPlims()
            self.viewLow = np.array([0, 0, plims[0]])
            self.viewHigh = np.array([self.vi.getDx(), self.vi.getDy(), plims[1]])
        except:
            pass    
    def DrawCriticalObjectsXZ(self):
        try:
            if( self.DEBUG ): print "DrawCriticalObjectsXZ"
            self.drawpoints = []
            plims = self.vi.getPlims()
            self.viewLow = np.array([0, plims[0], 0])
            self.viewHigh = np.array([self.vi.getDx(), plims[1],self.vi.getDz()])
        except:
            pass      
    def DrawCriticalObjectsYZ(self):
        try:
            if( self.DEBUG ): print "DrawCriticalObjectsYZ"
            plims = self.vi.getPlims()
            self.viewLow = np.array([plims[0], 0, 0])
            self.viewHigh = np.array([plims[1],self.vi.getDy(), self.vi.getDz()])
        except:
            pass
    def DrawCriticalObjects(self):
        try:
            if( self.DEBUG ): print "DrawCriticalObjects"
            if( self.vi.mode == 2 ):
                self.drawpoints = self.CriticalObjects[:]
                return
            if( self.vi.getViewType() == 'global' ):
                self.DrawAllCriticalObjects()
            else:
                if( self.vi.cview == 'xy' ):
                    self.DrawCriticalObjectsXY()
                elif( self.vi.cview == 'xz' ):
                    self.DrawCriticalObjectsXZ()
                else:
                    self.DrawCriticalObjectsYZ()
        except Exception, error:
            print "failed in DrawCriticalObjects", error

    def ResetScale(self):
        try:
            self.scale = 1
        except:
            pass
    def DecreaseScale(self):
        try:
            self.scale = max(1,self.scale-1)
        except:
            pass
    def IncreaseScale(self):
        try:
            self.scale = self.scale+1
        except:
            pass

    def SetViewXY(self):
        try:
            self.vi.setView(v = 'xy')
            self.DrawCriticalObjects()
        except Exception, error:
            pass
    def SetViewXZ(self):
        try:
            self.vi.setView(v = 'xz')
            self.DrawCriticalObjects()
        except Exception, error:
            print "failed in SetViewXZ",error
            pass
    def SetViewYZ(self):
        try:
            self.vi.setView(v = 'yz')
            self.DrawCriticalObjects()
        except Exception, error:
            print "failed in SetViewYZ", error


    def flipSliceUD(self):
        try:
            self.vi.toggleFlipUD()
            self.vi.winlevelimage()
        except Exception, error:
            print "flipSliceUD",error

    def flipSliceLR(self):
        try:
            self.vi.toggleFlipLR()
            self.vi.winlevelimage()
        except Exception, error:
            print "flipSliceLR",error

def getLabels(filename):
    try:
        fo = open(filename,'r')
        labels = fo.readlines()
        labels = [ l.strip() for l in labels ]
        return labels
    except Exception, error:
        print "failed in getLabelScheme", error
def getColors(filename):
    try:
        fo = open(filename,'r')
        colors = fo.readlines()
        colors = [ c.strip() for c in colors ]
        return colors
    except Exception, error:
        print "failed in getColors", error
        
def getWinLevelSettings(filename):
    try:
        wls = {}
        fo = open(filename,'r')
        data = fo.readlines()
        for d in data[1:]:# first line is header
            dd = d.split(',')
            wls[dd[0]] = {'win':int(dd[1]),'lev':int(dd[2])}
        return wls
    except Exception, error:
        print "failed in getWinLevelSettings", error
        
def getLabelScheme(labels, colors):
    try:
        colorScheme = {}
        # always use the first color uniquely for the first label
        colorScheme[labels[0]] = colors[0]

        numColors = len(colors)-1
        count = 0
        for l in labels[1:]:
            colorScheme[l] = colors[count % numColors +1]
            count += 1
        return colorScheme
    except Exception, error:
        print "failed in getLabelScheme", error
        print labels
        print colors
        return {"unlabeled":"Red","labeled":"Green"}

def getLabels(filename):
    try:
        fo = open(filename,'r')
        labels = fo.readlines()
        labels = [ l.strip() for l in labels ]
        return labels
    except Exception, error:
        print "failed in getLabelScheme", error


